// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CSubmissionExtension.
//   $Id$


#include "stdafx.h"
#include "SubmissionExtension.h"
#include "FP_ReturnCodes.h"

CSubmissionExtension::CSubmissionExtension(void)
{
}

CSubmissionExtension::~CSubmissionExtension(void)
{
}

HRESULT CSubmissionExtension::SetTemplate(IXMLDOMNode * pNodeTemplate)
{
	HRESULT hr = E_FAIL;
	m_pTemplateNode.Release(); 
	if(pNodeTemplate) {
		hr = pNodeTemplate->QueryInterface(&m_pTemplateNode);
	}

	return hr;
}

HRESULT CSubmissionExtension::SetInstance(IXMLDOMNode * pNodeInstance) {
	HRESULT hr = E_FAIL;
	m_pInstanceNode.Release();
	if(pNodeInstance) {
		hr = pNodeInstance->QueryInterface(&m_pInstanceNode);
	}

	return hr;
}

HRESULT CSubmissionExtension::get_evaluator(IXPathEvaluator ** pVal)
{
	return m_pEvaluator.CopyTo(pVal);
}

HRESULT  CSubmissionExtension::putref_evaluator(IXPathEvaluator * newVal)
{
	if(m_pEvaluator)
		m_pEvaluator.Release();

	m_pEvaluator = newVal;
	
	return S_OK;
}

HRESULT CSubmissionExtension::GetAction(CComBSTR &sAction)
{
	HRESULT hr = S_FALSE;
	CComPtr<IXMLDOMNodeList> pNl;
	if(m_pTemplateNode) {
		m_pTemplateNode->selectNodes(L"action/part",&pNl);
		CComPtr<IXMLDOMNode> pNChild;
		pNl->nextNode(&pNChild);

		if(pNChild)
			sAction = L"";

		while(pNChild && SUCCEEDED(hr))
		{
			CComBSTR sValue;
			hr = getNodeText(pNChild, sValue);
			// Bug 910 - Report error to the caller.
			if(SUCCEEDED(hr)) 
				sAction += sValue;
			else {
				hr = FP_E_INVLDSUBEXT;
				SetupErrorInfo(hr, L"action");
			}

			pNChild.Release();
			pNl->nextNode(&pNChild);
		}
	}

	return hr;
}

HRESULT CSubmissionExtension::GetInstanceRef(CComBSTR &sRef) {
	HRESULT hr = S_FALSE;
	CComPtr<IXMLDOMNodeList> pNl;
	if(m_pTemplateNode) {
		m_pTemplateNode->selectNodes(L"instance/ref/part",&pNl);
		CComPtr<IXMLDOMNode> pNChild;
		pNl->nextNode(&pNChild);

		if(pNChild)
			sRef = L"";

		while(pNChild && SUCCEEDED(hr))
		{
			CComBSTR sValue;
			hr = getNodeText(pNChild, sValue);
			// Bug 910 - Report error to the caller.
			if(SUCCEEDED(hr))
				sRef += sValue;
			else {
				hr = FP_E_INVLDSUBEXT;
				SetupErrorInfo(hr, L"instance/ref");
			}

			pNChild.Release();
			pNl->nextNode(&pNChild);
		}
	}

	return hr;
}

HRESULT CSubmissionExtension::GetInstanceBind(CComBSTR &sBind) {
	HRESULT hr = S_FALSE;
	CComPtr<IXMLDOMNodeList> pNl;
	if(m_pTemplateNode) {
		hr = m_pTemplateNode->selectNodes(L"instance/bind/part",&pNl);
		CComPtr<IXMLDOMNode> pNChild;
		pNl->nextNode(&pNChild);

		if(pNChild)
			sBind = L"";


		while(pNChild && SUCCEEDED(hr)) {
			CComBSTR sValue;
			hr = getNodeText(pNChild, sValue);
			// Bug 910 - Report error to the caller.
			if(SUCCEEDED(hr)) 
				sBind += sValue;
			else {
				hr = FP_E_INVLDSUBEXT;
				SetupErrorInfo(hr, L"instance/bind");
			}
			pNChild.Release();
			pNl->nextNode(&pNChild);
		}
	}

	return hr;
}

HRESULT CSubmissionExtension::GetEncoding(CComBSTR &sEncoding) {
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"encoding", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sEncoding = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"encoding");
	}
	
	return hr;
}

HRESULT CSubmissionExtension::GetReturnInstance(CComBSTR &sInstance) {
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"instance", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sInstance = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"instance");
	}
		
	return hr;
}

HRESULT CSubmissionExtension::GetMethod(CComBSTR &sMethod) { 
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"method", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sMethod = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"instance");
	}
	
	return hr;
}

HRESULT CSubmissionExtension::GetUsername(CComBSTR &sUsername) { 
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"username", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sUsername = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"username");
	}
	
	return hr;
}

HRESULT CSubmissionExtension::GetPassword(CComBSTR &sPassword) { 
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"password", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sPassword = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"password");
	}
	return hr;
}


HRESULT CSubmissionExtension::GetMediaType(CComBSTR &sMediaType) {
	HRESULT hr = S_FALSE;
	CComBSTR sValue;
	hr = getNodeText(L"mediatype", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue)
			sMediaType = sValue;
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"mediatype");
	}

	return hr;
}

HRESULT CSubmissionExtension::GetHeaders(CComBSTRMap &mHeadersList) {
	HRESULT hr = S_FALSE;

	CComPtr<IXMLDOMNodeList> pNl;
	if(m_pTemplateNode) {
		m_pTemplateNode->selectNodes(L"headers/header",&pNl);
		CComPtr<IXMLDOMNode> pNChild;
		pNl->nextNode(&pNChild);
		
		while(pNChild && SUCCEEDED(hr))
		{
			CComVariant vtName;
			CComQIPtr<IXMLDOMElement> pEl(pNChild);
			pEl->getAttribute(L"name",&vtName);
			//retrieve the value.
			CComBSTR sValue;
			hr = getNodeText(pNChild, sValue);
			// Bug 910 - Report error to the caller.
			if(SUCCEEDED(hr)) {
				//set the header with the given value.
				CComBSTR sName;
				vtName.CopyTo(&sName);
				// Add or over write the 
				mHeadersList[sName] = sValue;
			} else {
				hr = FP_E_INVLDSUBEXT;
				SetupErrorInfo(hr, L"headers/header");
			}
			//prepare next iteration
			pNChild.Release();
			pNl->nextNode(&pNChild);
		}
	}

	return hr;
}

HRESULT CSubmissionExtension::getNodeText(IXMLDOMNode * pTemplateNode, CComBSTR & bsValue)
{
	HRESULT hr = S_FALSE;
	CComQIPtr<IXMLDOMElement> pTemplateEl(pTemplateNode);
	if(pTemplateEl)
	{
		//Get the ref element
		CComVariant vtRef;
		
		if(S_OK == pTemplateEl->getAttribute(L"ref",&vtRef))
		{
			//Get the node referred to by the reef attribute
			CComPtr<IXPathResult> pResult;
			// Bug 910 - Report error to the caller.
			hr = m_pEvaluator->evaluate(vtRef.bstrVal,m_pInstanceNode,0,FIRST_ORDERED_NODE_TYPE,0,&pResult);
			CComPtr<IXMLDOMNode> pResultNode;
			if(pResult) {
				pResult->get_singleNodeValue(&pResultNode);
				if(pResultNode)
					hr = pResultNode->get_xml(&bsValue);
			}
		}
		else if(S_OK == pTemplateEl->getAttribute(L"value",&vtRef))
		{
			//otherwise, try to get a value element (non-node XPath)
			CComPtr<IXPathResult> pResult;
			// Bug 910 - Report error to the caller.
			hr = m_pEvaluator->evaluate(vtRef.bstrVal,m_pInstanceNode,0,STRING_TYPE,0,&pResult);
			if(pResult)
				hr = pResult->get_stringValue(&bsValue);
		}
		else
		{
			//otherwise, body is just inline text.
			hr = pTemplateNode->get_text(&bsValue);
		}
	}

	return hr;
}


HRESULT CSubmissionExtension::getNodeText(BSTR sTemplateXPath, CComBSTR & bsValue)
{
	HRESULT hr = S_FALSE;
	//Fetch the element that tells us how to format the body.
	CComPtr<IXMLDOMNode> pTemplate;
	if(m_pTemplateNode) {
		m_pTemplateNode->selectSingleNode(sTemplateXPath,&pTemplate);
		hr = getNodeText(pTemplate, bsValue);
	}

	return hr;
}

HRESULT CSubmissionExtension::GetSerialisation(CImplSubmitInfo::ESerialisation * peSerialisation) {
	HRESULT hr = S_FALSE;
	
	CComBSTR sValue;
	hr = getNodeText(L"serialisation", sValue);
	// Bug 910 - Report error to the caller.
	if(SUCCEEDED(hr)) {
		if(sValue) {
			if(wcsicmp(sValue, L"application/xml") == 0)
				*peSerialisation = CImplSubmitInfo::ESerialisation::xml;
			else if(wcsicmp(sValue, L"multipart/related") == 0)
				*peSerialisation = CImplSubmitInfo::ESerialisation::multipartRelated;
			else if(wcsicmp(sValue, L"multipart/form-data") == 0)
				*peSerialisation = CImplSubmitInfo::ESerialisation::multipartForm;
			else if(wcsicmp(sValue, L"application/x-www-form-urlencoded") == 0)
				*peSerialisation = CImplSubmitInfo::ESerialisation::nvpair;
		}
	} else {
		hr = FP_E_INVLDSUBEXT;
		SetupErrorInfo(hr, L"serialisation");
	}

	return hr;
}
